package com.xbts.system.service.impl;

import java.util.*;
import java.util.concurrent.*;

import cn.hutool.core.thread.ThreadUtil;
import com.huaweicloud.sdk.bss.v2.BssClient;
import com.huaweicloud.sdk.bss.v2.model.*;
import com.huaweicloud.sdk.bss.v2.region.BssRegion;
import com.huaweicloud.sdk.core.auth.BasicCredentials;
import com.huaweicloud.sdk.core.auth.GlobalCredentials;
import com.huaweicloud.sdk.core.auth.ICredential;
import com.huaweicloud.sdk.core.exception.ConnectionException;
import com.huaweicloud.sdk.core.exception.RequestTimeoutException;
import com.huaweicloud.sdk.core.exception.ServiceResponseException;
import com.huaweicloud.sdk.ecs.v2.EcsClient;
import com.huaweicloud.sdk.ecs.v2.model.Flavor;
import com.huaweicloud.sdk.ecs.v2.model.ListFlavorsResponse;
import com.huaweicloud.sdk.ecs.v2.region.EcsRegion;
import com.huaweicloud.sdk.iam.v3.model.KeystoneListProjectsResponse;
import com.huaweicloud.sdk.iam.v3.model.ProjectResult;
import com.xbts.common.constant.Constants;
import com.xbts.common.core.redis.RedisCache;
import com.xbts.common.enums.SettingEnum;
import com.xbts.common.utils.list.ListUtils;
import com.xbts.common.utils.bean.BeanUtils;
import com.xbts.system.domain.dto.AccountSetting;
import com.xbts.system.domain.dto.ListFlavorsRequestDTO;
import com.xbts.system.domain.dto.ListFlavorsResponseDTO;
import com.xbts.system.enums.EipEnum;
import com.xbts.system.service.ICloudServiceService;
import com.xbts.system.service.SettingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.xbts.system.domain.CnRegion;
import com.xbts.system.service.ICnRegionService;

import javax.annotation.PostConstruct;

/**
 * 华为云项目列Service业务层处理
 *
 * @author xbts
 * @date 2023-08-01
 */
@Service
@Slf4j
public class CnRegionServiceImpl implements ICnRegionService {

    @Autowired
    private RedisCache redisCache;
    @Autowired
    private SettingService settingService;

    @Autowired
    private ICloudServiceService cloudServiceService;

    private static List<CnRegion> cnRegionList = new ArrayList<>();

    public static List<CnRegion> getCnRegionList() {
        return cnRegionList;
    }

    /**
     * 初始化缓存
     */
    @PostConstruct
    public void init() {
        loadingCache();
        // TODO 部署时打开
//        this.initRegionMap();
    }

    public void loadingCache() {
        log.debug("初始化华为云项目列缓存");
        KeystoneListProjectsResponse keystoneListProjectsResponse = cloudServiceService.keystoneListProjects();
        List<ProjectResult> projects = keystoneListProjectsResponse.getProjects();
        // 在线查询当前华为云总帐号的项目id
        for (ProjectResult project : projects) {
            if (project.getName().equals("MOS")) {
                continue;
            }
//            if (project.getName().equals(xbtsConfig.getRegionId())) {
            CnRegion cnRegion = new CnRegion();
            cnRegion.setRegionId(project.getName());
            cnRegion.setEipType(EipEnum.getEip(project.getName()));
            cnRegion.setProjectId(project.getId());
            cnRegion.setEndPoint("ecs." + project.getName() + ".myhuaweicloud.com");
            cnRegion.setRegionName(getRegionMap().getOrDefault(project.getName(), null));
            cnRegionList.add(cnRegion);
//            }
        }
        cnRegionList.forEach(list -> redisCache.setCacheObject(Constants.REGION + list.getRegionId(), list));
    }

    /**
     * 查询华为云项目列
     *
     * @param regionId 华为云项目列主键
     * @return 华为云项目列
     */
    @Override
    public CnRegion selectCnRegionByRegionId(String regionId) {
        CnRegion cnRegion = redisCache.getCacheObject(Constants.REGION + regionId);
        if (cnRegion == null) {
            this.loadingCache();
            cnRegion = redisCache.getCacheObject(Constants.REGION + regionId);
        }
        return cnRegion;
    }

    public void initRegionMap() {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);

        Map<String, List<String>> notPriceMap = new HashMap<>();
        // 异步线程
        ThreadUtil.execAsync(() -> {
            log.debug("初始化华为云区域缓存");
            try {
                // 使用固定线程池查询云服务器规格列表
                ExecutorService executorService = Executors.newFixedThreadPool(20);
                int numberOfTasks = cnRegionList.size(); // 要执行的任务数量
                List<Future<String>> futures = new ArrayList<>();
                for (int i = 0; i < numberOfTasks; i++) {
                    final int taskId = i;
                    Future<String> future = executorService.submit(() -> {
                        StringBuilder result = new StringBuilder();
                        for (CnRegion cnRegion : cnRegionList) {
                            ListFlavorsRequestDTO listFlavorsRequest = new ListFlavorsRequestDTO();
                            String regionId = cnRegion.getRegionId();
                            ICredential auth = new BasicCredentials()
                                    .withAk(accountSetting.getAccessKeyId())
                                    .withSk(accountSetting.getSecretAccessKey());
                            EcsClient client = EcsClient.newBuilder()
                                    .withCredential(auth)
                                    .withRegion(EcsRegion.valueOf(regionId))
                                    .build();

                            ListFlavorsResponse response = null;
                            try {
                                response = client.listFlavors(listFlavorsRequest);
                                // 获取规格价格
                            } catch (ConnectionException | ServiceResponseException | RequestTimeoutException e) {
                                log.error("查询云服务器规格列表失败", e);
                                continue;
                            }
//                    if (null == response || response.getFlavors().isEmpty()) return null;
                            ICredential iCredential = new GlobalCredentials()
                                    .withAk(accountSetting.getAccessKeyId())
                                    .withSk(accountSetting.getSecretAccessKey());
                            BssClient bssClient = BssClient.newBuilder()
                                    .withCredential(iCredential)
                                    .withRegion(BssRegion.valueOf("cn-north-1"))
                                    .build();
                            ListRateOnPeriodDetailRequest listRateOnPeriodDetailRequest = new ListRateOnPeriodDetailRequest();
                            RateOnPeriodReq body = new RateOnPeriodReq();
                            ListFlavorsResponseDTO listFlavorsResponseDTO = new ListFlavorsResponseDTO();
                            BeanUtils.copyBeanProp(listFlavorsResponseDTO, response);
                            listFlavorsResponseDTO.setRegionId(regionId);
                            listFlavorsResponseDTO.setProjectId(cnRegion.getProjectId());

                            List<PeriodProductInfo> listbodyProductInfos = this.getFlavorsParams(listFlavorsResponseDTO);

                            List<List<PeriodProductInfo>> lists = ListUtils.divideArrays(listbodyProductInfos, 100);
                            List<String> notPriceList = new ArrayList<>();
                            for (int j = 0; j < lists.size(); j++) {
                                List<PeriodProductInfo> periodProductInfos = lists.get(j);
                                for (PeriodProductInfo periodProductInfo : periodProductInfos) {
                                    String resourceSpec = periodProductInfo.getResourceSpec();
                                    log.info("resourceSpec = " + resourceSpec);
                                    body.withProductInfos(Collections.singletonList(periodProductInfo));
                                    body.withProjectId(cnRegion.getProjectId());
                                    listRateOnPeriodDetailRequest.withBody(body);
                                    try {
                                        bssClient.listRateOnPeriodDetail(listRateOnPeriodDetailRequest);
                                    } catch (Exception e) {
                                        notPriceList.add(periodProductInfo.getResourceSpec());
                                    }
                                }
                            }
                            if (cnRegion.getProjectId().equals("cn-east-3")){
                                System.out.println("notPriceList = " + notPriceList);
                            }
                            notPriceMap.put(regionId, notPriceList);
                        }
                        result.append("任务 ").append(taskId).append("正在执行");
                        return result.toString();
                    });
                    futures.add(future);
                }
                log.debug("初始化华为云区域缓存完成");
                // 将notPriceMap缓存至redis
                notPriceMap.forEach((k, v) -> redisCache.setCacheObject(Constants.REGION_IGNORE_FLAVOR_KEY + k, v));
            } catch (Exception e) {
                log.error("查询云服务器规格列表失败", e);
            }
        });
    }

    public List<PeriodProductInfo> getFlavorsParams(ListFlavorsResponseDTO listFlavorsResponseDTO) {
        if (listFlavorsResponseDTO == null) {
            return null;
        }
        List<PeriodProductInfo> periodProductInfos = new ArrayList<>(listFlavorsResponseDTO.getFlavors().size());
        List<Flavor> flavors = listFlavorsResponseDTO.getFlavors();

        for (int i = 0; i < flavors.size(); i++) {
            Flavor flavor = flavors.get(i);
            PeriodProductInfo periodProductInfo = new PeriodProductInfo();
            periodProductInfo.setId(String.valueOf(i + 1));
            periodProductInfo.setCloudServiceType("hws.service.type.ec2");
            periodProductInfo.setResourceType("hws.resource.type.vm");
            periodProductInfo.setResourceSpec(flavor.getName() + ".linux");
            periodProductInfo.setRegion(listFlavorsResponseDTO.getRegionId());
            periodProductInfo.setPeriodType(2);
            periodProductInfo.setPeriodNum(1);
            periodProductInfo.setSubscriptionNum(1);
            periodProductInfos.add(periodProductInfo);
        }
        // 过滤不支持包年包月的规格
        return periodProductInfos;
    }

    public Map<String, String> getRegionMap() {
        Map<String, String> regionMap = new HashMap<>();
        regionMap.put("af-south-1", "非洲-约翰内斯堡");
        regionMap.put("cn-north-4", "华北-北京四");
        regionMap.put("cn-north-1", "华北-北京一");
        regionMap.put("cn-north-9", "华北-乌兰察布一");
        regionMap.put("cn-east-2", "华东-上海二");
        regionMap.put("cn-east-3", "华东-上海一");
        regionMap.put("cn-south-1", "华南-广州");
        regionMap.put("cn-south-4", "华南-广州-友好用户环境");
        regionMap.put("cn-south-2", "华南-深圳");
        regionMap.put("na-mexico-1", "拉美-墨西哥城一");
        regionMap.put("la-south-2", "拉美-圣地亚哥");
        regionMap.put("eu-west-0", "欧洲-巴黎");
        regionMap.put("eu-west-101", "欧洲-都柏林");
        regionMap.put("tr-west-1", "土耳其-伊斯坦布尔");
        regionMap.put("cn-southwest-2", "西南-贵阳一");
        regionMap.put("ap-southeast-2", "亚太-曼谷");
        regionMap.put("ap-southeast-3", "亚太-新加坡");
        regionMap.put("ae-ad-1", "中东-阿布扎比-OP5");
        regionMap.put("me-east-1", "中东-利雅得");
        regionMap.put("ap-southeast-1", "中国-香港");
        return regionMap;
    }
}
